home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / rules / prs2 / prs2rel.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-27  |  10.4 KB  |  374 lines

  1. /*=======================================================================
  2.  * FILE:
  3.  *   prs2rel.c
  4.  *
  5.  * IDENTIFICATION:
  6.  *   $Header: /private/postgres/src/rules/prs2/RCS/prs2rel.c,v 1.11 1992/07/13 06:10:28 mao Exp $
  7.  *
  8.  * DESCRIPTION:
  9.  *
  10.  *   Code for putting/removing relation level locks:
  11.  *   Relation level locks are stored in pg_relation. All the
  12.  *   tuples of the coresponding relation are assumed to be locked by
  13.  *   these locks.
  14.  *   Relation Level locks are used by both the tuple-level & the query
  15.  *   rewrite rule systems. However the tuple-level system can also
  16.  *   use tuple-level locks.
  17.  *        
  18.  *=======================================================================
  19.  */
  20.  
  21. #include "tmp/postgres.h"
  22. #include "nodes/primnodes.h"
  23. #include "nodes/primnodes.a.h"
  24. #include "nodes/pg_lisp.h"
  25. #include "utils/log.h"
  26. #include "utils/relcache.h"    /* RelationNameGetRelation() defined here...*/
  27. #include "rules/prs2.h"
  28. #include "rules/prs2stub.h"
  29. #include "access/skey.h"    /* 'ScanKeyEntryData' defined here... */
  30. #include "access/tqual.h"    /* 'NowTimeQual' defined here.. */
  31. #include "access/heapam.h"    /* heap AM calls defined here */
  32. #include "utils/lsyscache.h"    /* for get_attnum(), get_rel_name() ...*/
  33. #include "parser/parse.h"    /* RETRIEVE, APPEND etc defined here.. */
  34. #include "parser/parsetree.h"
  35. #include "catalog/catname.h"    /* names of various system relations */
  36. #include "utils/fmgr.h"    /* for F_CHAR16EQ, F_CHAR16IN etc. */
  37. #include "access/ftup.h"    /* for FormHeapTuple() */
  38. #include "utils/palloc.h"
  39.  
  40. #include "catalog/pg_proc.h"
  41. #include "catalog/pg_prs2rule.h"
  42. #include "catalog/pg_prs2plans.h"
  43.  
  44. Prs2Stub prs2FindStubsThatDependOnAttribute();
  45.  
  46. /*-----------------------------------------------------------------------
  47.  * prs2DefRelationLevelLockRule
  48.  *
  49.  * Put the appropriate locks for a tuple-system rule that is implemented
  50.  * with a relation level lock.
  51.  *
  52.  * We have to do two things:
  53.  * a) put the relation level lock for this rule (easy!)
  54.  * b) If this is a "on retrieve ... do retrieve" rule, i.e.
  55.  * if it places a "write" lock to an attribute, then we must find all
  56.  * the tuple-level-lock rules that reference this attribute in their
  57.  * qualification and change them to relation-level-lock rules too.
  58.  * (see the discussion in the comments in "prs2putlocks.c"...)
  59.  *-----------------------------------------------------------------------
  60.  */
  61. void
  62. prs2DefRelationLevelLockRule(r)
  63. Prs2RuleData r;
  64. {
  65.     RuleLock oldLocks, newLocks;
  66.     LispValue actionPlans;
  67.     Name relationName;
  68.     Prs2Stub relstubs, stubs, newstubs;
  69.     ObjectId *ruleoids;
  70.     int nrules;
  71.     int i;
  72.     AttributeNumber attributeNo;
  73.     Prs2LockType lockType;
  74.  
  75.  
  76.     /*
  77.      * insert the appropriate info in the system catalogs.
  78.      * (and find the rule oid)
  79.      */
  80.     r->ruleId = prs2InsertRuleInfoInCatalog(r);
  81.  
  82.     actionPlans = prs2GenerateActionPlans(r);
  83.     prs2InsertRulePlanInCatalog(r->ruleId, ActionPlanNumber, actionPlans);
  84.  
  85.     /*
  86.      * find the loc type and the attribute that must be locked
  87.      */
  88.     prs2FindLockTypeAndAttrNo(r, &lockType, &attributeNo);
  89.  
  90.  
  91.     /*
  92.      * Find the relation level locks of the relation
  93.      */
  94.     relationName = get_rel_name(r->eventRelationOid);
  95.     oldLocks = prs2GetLocksFromRelation(relationName);
  96.  
  97.     /*
  98.      * now claculate the new locks
  99.      */
  100.     newLocks = prs2CopyLocks(oldLocks);
  101.     newLocks = prs2AddLock(newLocks,
  102.             r->ruleId,
  103.             lockType,
  104.             attributeNo,
  105.             ActionPlanNumber, /* 'ActionPlanNumber' is a constant */
  106.             0,            /* partial indx - UNUSED */
  107.             0);            /* npartial - UNUSED  */
  108.  
  109.     /*
  110.      * if this is a "write" lock, we might have to change some other
  111.      * rules too (from tuple-level-lock to relation-level-lock).
  112.      */
  113.     if (lockType == LockTypeRetrieveWrite) {
  114.     /*
  115.      * find all the tuple-level-lock rules that must be changed
  116.      * to relation-level-lock...
  117.      * Look at the (relation level) stubs of this relation.
  118.      * and find all the stubs that "depend" on "attributeNo"
  119.      * (the attribute to be locked by a "write" lock).
  120.      */
  121.     relstubs = prs2GetRelationStubs(r->eventRelationOid);
  122.     stubs = prs2FindStubsThatDependOnAttribute(relstubs, attributeNo);
  123.     /*
  124.      * now get the rule oids from the stubs & store them in an
  125.      * array.
  126.      */
  127.     nrules = stubs->numOfStubs;
  128.     if (nrules>0) {
  129.         ruleoids = (ObjectId *) palloc(nrules * sizeof(ObjectId));
  130.         if (ruleoids==NULL) {
  131.         elog(WARN,"prs2DefRelationLevelLockRule: out of memory!");
  132.         }
  133.     }
  134.     for (i=0; i<nrules; i++) {
  135.         ruleoids[i] = stubs->stubRecords[i]->ruleId;
  136.     }
  137.  
  138. #ifdef PRS2_DEBUG
  139.     {
  140.         int k;
  141.  
  142.         printf(
  143.         "PRS2: the following rules will change from TupLev to RelLev\n");
  144.         printf("PRS2:");
  145.         for (k=0; k<nrules; k++) {
  146.         printf(" %ld", ruleoids[k]);
  147.         }
  148.         printf("\n");
  149.     }
  150. #endif PRS2_DEBUG
  151.  
  152.     /*
  153.      * now remove their tuple level locks and stubs..
  154.      */
  155.     prs2RemoveTupleLeveLocksAndStubsOfManyRules(r->eventRelationOid,
  156.                             ruleoids,
  157.                             nrules);
  158.     /*
  159.      * finally, these rules must be implemented with a relation
  160.      * level lock, so add the appropriate locks to 'newLocks'
  161.      */
  162.     for (i=0; i<nrules; i++) {
  163.         newLocks = prs2LockUnion(newLocks, stubs->stubRecords[i]->lock);
  164.     }
  165.     }
  166.  
  167.     /*
  168.      * OK, now update the relation-level-locks of the relation.
  169.      */
  170.     prs2SetRelationLevelLocks(r->eventRelationOid, newLocks);
  171.  
  172. }
  173.  
  174. /*--------------------------------------------------------------
  175.  *
  176.  * prs2UndefRelationLevelLockRule
  177.  *
  178.  * remove a rule that uses relation level locks...
  179.  * delete its relation level lock & all the info from the
  180.  * system catalogs.
  181.  *--------------------------------------------------------------
  182.  */
  183. void
  184. prs2UndefRelationLevelLockRule(ruleId, relationId)
  185. ObjectId ruleId;
  186. ObjectId relationId;
  187. {
  188.  
  189.     /*
  190.      * first remove the relation level lock
  191.      */
  192.     prs2RemoveRelationLevelLocksOfRule(ruleId, relationId);
  193.  
  194.     /*
  195.      * Finally remove the system catalog info...
  196.      */
  197.     prs2DeleteRulePlanFromCatalog(ruleId);
  198.     prs2DeleteRuleInfoFromCatalog(ruleId);
  199.  
  200. }
  201.  
  202. /*-----------------------------------------------------------------------
  203.  * prs2RemoveRelationLevelLocksOfRule
  204.  *
  205.  * remove the relation level locks of the given rule
  206.  *
  207.  *-----------------------------------------------------------------------
  208.  */
  209. void
  210. prs2RemoveRelationLevelLocksOfRule(ruleId, relationId)
  211. ObjectId ruleId;
  212. ObjectId relationId;
  213. {
  214.     RuleLock currentLocks;
  215.     RuleLock newLocks;
  216.     Name relationName;
  217.  
  218.     /*
  219.      * first find the current locks of the relation
  220.      */
  221.     relationName = get_rel_name(relationId);
  222.     if (relationName == NULL) {
  223.     /*
  224.      * complain, but do not abort the transaction
  225.      * so that we can remove a rule, even if we have
  226.      * accidentally destroyed the corresponding relation...
  227.      */
  228.     elog(NOTICE, "prs2RemoveRelationLevelLocksOfRule: can not find rel %d",
  229.         relationId);
  230.     return;
  231.     }
  232.  
  233.     currentLocks = prs2GetLocksFromRelation(relationName);
  234. #ifdef PRS2_DEBUG
  235.     printf("PRS2: Remove RelationLevelLock of rule %d from rel=%s\n",
  236.     ruleId, relationName);
  237. #endif PRS2_DEBUG
  238.  
  239.     /*
  240.      * Now calculate the new locks
  241.      */
  242.     newLocks = prs2RemoveAllLocksOfRule(currentLocks, ruleId);
  243.  
  244.     /*
  245.      * Now, update the locks of the relation
  246.      */
  247.     prs2SetRelationLevelLocks(relationId, newLocks);
  248. }
  249.  
  250. /*-----------------------------------------------------------------------
  251.  * prs2SetRelationLevelLocks
  252.  *
  253.  * Set the relation level locks for a relation to the given ones.
  254.  * These locks are stored in the appropriate tuple of pg_relation.
  255.  * All the tuples of the target relation are assumed to be locked
  256.  *
  257.  * Relation level locks are used by both the tuple-level system and
  258.  * the query rewrite system.
  259.  *
  260.  *-----------------------------------------------------------------------
  261.  */
  262.  
  263. void
  264. prs2SetRelationLevelLocks(relationId, newLocks)
  265. ObjectId relationId;
  266. RuleLock newLocks;
  267. {
  268.  
  269.     Relation relationRelation;
  270.     HeapScanDesc scanDesc;
  271.     ScanKeyData scanKey;
  272.     HeapTuple tuple;
  273.     Buffer buffer;
  274.     HeapTuple newTuple;
  275.  
  276.     /*
  277.      * Lock a relation given its ObjectId.
  278.      * Go to the RelationRelation (i.e. pg_relation), find the
  279.      * appropriate tuple, and add the specified lock to it.
  280.      */
  281.     relationRelation = RelationNameOpenHeapRelation(RelationRelationName);
  282.  
  283.     ScanKeyEntryInitialize(&scanKey.data[0], 0, ObjectIdAttributeNumber,
  284.                            ObjectIdEqualRegProcedure, 
  285.                            ObjectIdGetDatum(relationId));
  286.  
  287.     scanDesc = RelationBeginHeapScan(relationRelation,
  288.                     false, NowTimeQual,
  289.                     1, &scanKey);
  290.     
  291.     tuple = HeapScanGetNextTuple(scanDesc, false, &buffer);
  292.     if (!HeapTupleIsValid(tuple)) {
  293.     elog(WARN, "prs2SetRelationLevelLocks: Invalid rel OID %ld",
  294.         relationId);
  295.     }
  296.  
  297. #ifdef PRS2_DEBUG
  298.     {
  299.     RuleLock l;
  300.  
  301.     l = prs2GetLocksFromTuple(tuple, buffer);
  302.     printf(
  303.         "PRS2:prs2SetRelationLevelLocks: Updating locks of relation %d\n",
  304.         relationId);
  305.     printf("PRS2: Old RelLev Locks = ");
  306.     prs2PrintLocks(l);
  307.     printf("\n");
  308.     printf("PRS2: New RelLev Locks = ");
  309.     prs2PrintLocks(newLocks);
  310.     printf("\n");
  311.     }
  312. #endif PRS2_DEBUG
  313.  
  314.     /*
  315.      * Create a new tuple (i.e. a copy of the old tuple
  316.      * with its rule lock field changed and replace the old
  317.      * tuple in the RelationRelation
  318.      * NOTE: XXX ??? do we really need to make that copy ????
  319.      */
  320.     newTuple = palloctup(tuple, buffer, relationRelation);
  321.     prs2PutLocksInTuple(newTuple, InvalidBuffer, relationRelation, newLocks);
  322.  
  323.     RelationReplaceHeapTuple(relationRelation, &(tuple->t_ctid),
  324.                 newTuple, (double *)NULL);
  325.     
  326.     RelationCloseHeapRelation(relationRelation);
  327.     HeapScanEnd(scanDesc);
  328.  
  329. }
  330.  
  331.  
  332. /*-------------------------------------------------------------------
  333.  * prs2AddRelationLevelLock
  334.  *
  335.  * create & add a new relation level lock to the given relation.
  336.  *
  337.  *-------------------------------------------------------------------
  338.  */
  339. void
  340. prs2AddRelationLevelLock(ruleId, lockType, relationId, attrNo)
  341. ObjectId ruleId;
  342. Prs2LockType lockType;
  343. ObjectId relationId;
  344. AttributeNumber attrNo;
  345. {
  346.     RuleLock currentLocks;
  347.     RuleLock newLocks;
  348.     Name relationName;
  349.  
  350.     /*
  351.      * first find the current locks of the relation
  352.      */
  353.     relationName = get_rel_name(relationId);
  354.     currentLocks = prs2GetLocksFromRelation(relationName);
  355.  
  356.     /*
  357.      * Now calculate the new locks
  358.      */
  359.     newLocks = prs2AddLock(currentLocks,
  360.             ruleId,
  361.             lockType,
  362.             attrNo,
  363.             ActionPlanNumber, /* ActionPlanNumber is a constant.*/
  364.             0,          /* partialindx - UNUSED */
  365.             0);          /* npartial - UNUSED */
  366.  
  367.     /*
  368.      * Now, update the locks of the relation
  369.      */
  370.     prs2SetRelationLevelLocks(relationId, newLocks);
  371.  
  372. }
  373.  
  374.